/**
 *******************************************************************************
 * @file adc_driver.c
 * @author .ISS_AUTO (hudandan@issauto.com)
 * @date    2025-05-09   1. 添加ADC1,ADC3配置使能宏定义。
 *                       2. 添加ADC1,ADC3低功耗配置。
 *
 *
 * @note    注：用户需根据项目实际应用自行完成ADC GPIO的配置。
 *
 * @brief This file is for the ADC DMA configuration.
 *
 * @copyright Copyright (c) 2025 ISSAUTO TECH Co., Ltd. All rights reserved.
 *
 *******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "adc_driver.h"

/* Exported Function ---------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ADC_DMA_DriverTypeDef adc1_dma_driver = {0};
ADC_DMA_DriverTypeDef adc3_dma_driver = {0};

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
 * @brief ADC1 Low Power Configuration.
 *
 * @param[in] void
 * @return void
 */
void ADC1_LP_Configuration(void)
{
    /* Disable ADC1 DMA */
    ADC_EnableDMA(ADC1, DISABLE);

    /* Disable ADC1 */
    ADC_Enable(ADC1, DISABLE);

    /* DMA interrupt init */
    /* DMA1_Channel1_IRQn interrupt configuration */
    DMA_ConfigInt(DMA1_CH1, DMA_INT_TXC, DISABLE);

    /* Disable DMA1 channel1 */
    DMA_EnableChannel(DMA1_CH1, DISABLE);
}

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
void ADC1_Configuration(void *arg)
{
    ISS_ASSERT(arg != NULL);

    ADC_InitType ADC_InitStructure;
    // DMA_InitType DMA_InitStructure;
    GPIO_InitType GPIO_InitStructure;
    NVIC_InitType NVIC_InitStructure;

    memcpy((void *)&adc1_dma_driver, (void *)arg, sizeof(ADC_DMA_DriverTypeDef));

    /* Initializes peripheral gpio ------------------------------------------------*/
    /* Enable GPIOA clocks */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    /* Configure PA0() & PA1() as analog input */
    GPIO_InitStructure.Pin       = GPIO_PIN_0 | GPIO_PIN_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    /* Enable DMA1 clocks ----------------------------------------------*/
    DMA_DeInit(DMA1_CH1);

    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);

    /* DMA1 channel1 configuration ----------------------------------------------*/
    // DMA_InitStructure.PeriphAddr     = adc1_dma_driver.DMA_InitParam.PeriphAddr;
    // DMA_InitStructure.MemAddr        = adc1_dma_driver.DMA_InitParam.MemAddr;
    // DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    // DMA_InitStructure.BufSize        = adc1_dma_driver.DMA_InitParam.BufSize;
    // DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    // DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    // DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
    // DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_HalfWord;
    // DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;
    // DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    // DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    // DMA_Init(DMA1_CH1, &DMA_InitStructure);
    DMA_Init(DMA1_CH1, &(adc1_dma_driver.DMA_InitParam));

    /* DMA interrupt init */
    /* DMA1_Channel1_IRQn interrupt configuration */
    NVIC_InitStructure.NVIC_IRQChannel                   = DMA1_Channel1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x00; //!< Highest 0 Lowest 8
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    DMA_ConfigInt(DMA1_CH1, DMA_INT_TXC, ENABLE);

    /* Enable DMA1 channel1 */
    DMA_EnableChannel(DMA1_CH1, ENABLE);

    /* ADC1 configuration ------------------------------------------------------*/
    /* Enable ADC1 clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1, ENABLE);

    /* RCC_ADCHCLK_DIV16 */
    ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);

    ADC_InitStructure.WorkMode       = ADC_WORKMODE_INDEPENDENT;
    ADC_InitStructure.MultiChEn      = ENABLE;
    ADC_InitStructure.ContinueConvEn = ENABLE;
    ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;
    ADC_InitStructure.ChsNumber      = 2; //!< 📌Number of ADC1 regular channels
    ADC_Init(ADC1, &ADC_InitStructure);

    // ADC_SetConvResultBitNum(ADC1, ADC_RST_BIT_10); //!< 20231020

    /* ADC1 regular channelx configuration */
    ADC_ConfigRegularChannel(ADC1, ADC1_Channel_01_PA0, 1, ADC_SAMP_TIME_55CYCLES5);
    ADC_ConfigRegularChannel(ADC1, ADC1_Channel_02_PA1, 2, ADC_SAMP_TIME_55CYCLES5);

    /* Enable ADC1 DMA */
    ADC_EnableDMA(ADC1, ENABLE);

    /* Enable ADC1 */
    ADC_Enable(ADC1, ENABLE);

    /* Check ADC Ready */
    while (ADC_GetFlagStatusNew(ADC1, ADC_FLAG_RDY) == RESET)
        ;

    /* Start ADC1 calibration */
    ADC_StartCalibration(ADC1);

    /* Check the end of ADC1 calibration */
    while (ADC_GetCalibrationStatus(ADC1))
        ;

    /* Start ADC1 Software Conversion */
    ADC_EnableSoftwareStartConv(ADC1, ENABLE);

}

/**
 * @brief ADC3 Low Power Configuration.
 *
 * @param[in] void
 * @return void
 */
void ADC3_LP_Configuration(void)
{
    /* Disable ADC3 DMA */
    ADC_EnableDMA(ADC3, DISABLE);

    /* Disable ADC3 */
    ADC_Enable(ADC3, DISABLE);

    /* DMA interrupt init */
    /* DMA2_Channel5_IRQn interrupt configuration */
    DMA_ConfigInt(DMA2_CH5, DMA_INT_TXC, DISABLE);

    /* Disable DMA2 channel5 */
    DMA_EnableChannel(DMA2_CH5, DISABLE);
}

/**
  * @brief ADC3 Initialization Function
  * @param None
  * @retval None
  */
void ADC3_Configuration(void *arg)
{
    ISS_ASSERT(arg != NULL);

    ADC_InitType ADC_InitStructure;
    // DMA_InitType DMA_InitStructure;
    GPIO_InitType GPIO_InitStructure;
    NVIC_InitType NVIC_InitStructure;

    memcpy((void *)&adc3_dma_driver, (void *)arg, sizeof(ADC_DMA_DriverTypeDef));

    /* Initializes peripheral gpio ------------------------------------------------*/
    /* Enable GPIOB clocks */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);

    /* Configure PB11(V_REL) as analog input */
    GPIO_InitStructure.Pin       = GPIO_PIN_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);

    /* Enable DMA2 clocks ----------------------------------------------*/
    DMA_DeInit(DMA2_CH5);

    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA2, ENABLE);

    /* DMA2 channel5 configuration ----------------------------------------------*/
    // DMA_InitStructure.PeriphAddr     = adc3_dma_driver.DMA_InitParam.PeriphAddr;
    // DMA_InitStructure.MemAddr        = adc3_dma_driver.DMA_InitParam.MemAddr;
    // DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    // DMA_InitStructure.BufSize        = adc3_dma_driver.DMA_InitParam.BufSize;
    // DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    // DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    // DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
    // DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_HalfWord;
    // DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;
    // DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    // DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    // DMA_Init(DMA2_CH5, &DMA_InitStructure);
    DMA_Init(DMA2_CH5, &(adc3_dma_driver.DMA_InitParam));

    /* DMA interrupt init */
    /* DMA1_Channel8_IRQn interrupt configuration */
    NVIC_InitStructure.NVIC_IRQChannel                   = DMA2_Channel5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0x05; //!< Highest 0 Lowest 8
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    DMA_ConfigInt(DMA2_CH5, DMA_INT_TXC, ENABLE);

    /* Enable DMA2 channel5 */
    DMA_EnableChannel(DMA2_CH5, ENABLE);

    /* ADC3 configuration ------------------------------------------------------*/
    /* Enable ADC3 clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC3, ENABLE);

    /* RCC_ADCHCLK_DIV16 */
    ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);

    ADC_InitStructure.WorkMode       = ADC_WORKMODE_INDEPENDENT;
    ADC_InitStructure.MultiChEn      = ENABLE;
    ADC_InitStructure.ContinueConvEn = ENABLE;
    ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;
    ADC_InitStructure.ChsNumber      = 1; //!< 📌Number of ADC3 regular channels
    ADC_Init(ADC3, &ADC_InitStructure);

    /* ADC3 regular channel14 configuration */
    ADC_ConfigRegularChannel(ADC3, ADC3_Channel_01_PB11, 1, ADC_SAMP_TIME_239CYCLES5);

    /* Enable ADC3 DMA */
    ADC_EnableDMA(ADC3, ENABLE);

    /* Enable ADC3 */
    ADC_Enable(ADC3, ENABLE);

    /* Check ADC Ready */
    while (ADC_GetFlagStatusNew(ADC3, ADC_FLAG_RDY) == RESET)
        ;

    /* Start ADC3 calibration */
    ADC_StartCalibration(ADC3);

    /* Check the end of ADC3 calibration */
    while (ADC_GetCalibrationStatus(ADC3))
        ;

    /* Start ADC3 Software Conversion */
    ADC_EnableSoftwareStartConv(ADC3, ENABLE);

}

/* END OF FILE ---------------------------------------------------------------*/
